package src.ee.ioc.smaug.world;

import java.io.*;
import java.util.ArrayList;
import java.util.logging.*;

import src.ee.ioc.smaug.fsm.Alphabet;
import src.ee.ioc.smaug.world.evolution.EnvDescription;

public class Enviroment {

    /**
     * Number of states
     */
    public static int numberOfStates;

    /**
     * Alphabet of input data
     */
    public static Alphabet inAlphabet;

    /**
     * Alphabet of output data
     */
    public static Alphabet outAlphabet;

    /**
     * input data
     */
    public static ArrayList<String> inputData;

    /**
     * output data
     */
    public static ArrayList<String> outputData;

    /**
     * for reading training  data
     */
    static BufferedReader dataR;

    /**
     * Maximal possible fitness value
     */
    public static int bestFitness = 0;

    
    
    /**
     * Resulting file 
     */
    public static PrintWriter results;
    
    /**
     * Trace file 
     */
    public static PrintWriter trace;
    /**
     * Logger
     */
    public static Logger logger = Logger.getLogger("src.evolution.Enviroment");

    /**
     * Define logger
     */
    public static void defineLog() {
        try {
            FileHandler fh = new FileHandler(EnvDescription.LOGfilename);
            fh.setFormatter(new LoggingXMLFormatter());
            Enviroment.logger.addHandler(fh);
            Enviroment.logger.setLevel(EnvDescription.loglevel);
        } catch (IOException e) {
        }
    }

    /**
     * Reading training data
     * @throws IOException
     */
    public static void readData() throws IOException {
        inputData = new ArrayList<String>();
        outputData = new ArrayList<String>();
        try {
            dataR = new BufferedReader(new FileReader(EnvDescription.dataFile));

            String s = new String();
            while ((s = dataR.readLine()) != null) {
                String in = "";
                String out = "";
                boolean end = false;
                for (int i = 0; i < s.length(); i++) {

                    if ((s.charAt(i) == ',') || (s.charAt(i) == ' ')) {
                        end = true;
                    } else {
                        if (!end) {
                            in += s.charAt(i);
                        } else {
                            out += s.charAt(i);
                        }
                    }

                }

                inputData.add(in);
                outputData.add(out);
            }

        } catch (IOException e) {
            System.err.println("Error in input/output process...");
        } finally {
            dataR.close();
        }

    }

    /**
     * Creating enviroment, reading training data, defining size of the fsm and alphabets
     * @throws IOException
     */
    public static void create() throws IOException {
        numberOfStates = EnvDescription.numberOfStates;
        defineLog();

        logger.fine("Log file was created");

        readData();

        logger.fine("Training data was processed");

        Alphabet alpha = new Alphabet();
        Alphabet beta = new Alphabet();
        addCharsToAplhabet(alpha, inputData);
        addCharsToAplhabet(beta, outputData);
        inAlphabet = alpha;
        outAlphabet = beta;

        bestFitness = countMaxFitness();

        logger.fine("Enviroment was defined");
        
    }

    /**
     * Adding symbols to alphabet
     * @param alpha alphabet
     * @param list array of strings containing input/output data
     */
    private static void addCharsToAplhabet(Alphabet alpha,
            ArrayList<String> list) {
        for (int i = 0; i < list.size(); i++) {
            String li = list.get(i);
            for (int j = 0; j < li.length(); j++) {
                alpha.addToAlphabet(li.charAt(j));
            }
        }
    }

    /**
     * Summing up lengths of all strings in input data
     * @return maximal possible fitness value
     */
    private static int countMaxFitness() {
        int fv = 0;
        for (int i = 0; i < outputData.size(); i++) {
            fv += outputData.get(i).length();
        }
        return fv;
    }

}
